nwp500.models package

Submodules

nwp500.models.device module

class nwp500.models.device.Device(*, deviceInfo: DeviceInfo, location: Location)[source]

Bases: NavienBaseModel

Complete device information including location.

device_info: DeviceInfo
location: Location
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

with_info(info: DeviceInfo) Self[source]

Return a new Device instance with updated DeviceInfo.

class nwp500.models.device.DeviceInfo(*, homeSeq: int = 0, macAddress: str = '', additionalValue: str = '', deviceType: DeviceType | int = DeviceType.NPF700_WIFI, deviceName: str = 'Unknown', connected: ConnectionStatus, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.enum_validator.<locals>.validate, json_schema_input_type=PydanticUndefined)] = ConnectionStatus.DISCONNECTED, installType: str | None = None)[source]

Bases: NavienBaseModel

Device information from API.

additional_value: str
connected: validate, json_schema_input_type=PydanticUndefined)]
device_name: str
device_type: DeviceType | int
home_seq: int
install_type: str | None
mac_address: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class nwp500.models.device.FirmwareInfo(*, macAddress: str = '', additionalValue: str = '', deviceType: DeviceType | int = DeviceType.NPF700_WIFI, curSwCode: int = 0, curVersion: int = 0, downloadedVersion: int | None = None, deviceGroup: str | None = None)[source]

Bases: NavienBaseModel

Firmware information for a device.

additional_value: str
cur_sw_code: int
cur_version: int
device_group: str | None
device_type: DeviceType | int
downloaded_version: int | None
mac_address: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class nwp500.models.device.Location(*, state: str | None = None, city: str | None = None, address: str | None = None, latitude: float | None = None, longitude: float | None = None, altitude: float | None = None)[source]

Bases: NavienBaseModel

Location information for a device.

address: str | None
altitude: float | None
city: str | None
latitude: float | None
longitude: float | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

state: str | None

nwp500.models.energy module

class nwp500.models.energy.EnergyUsageBase(*, hpUsage: int = 0, heUsage: int = 0, hpTime: int = 0, heTime: int = 0)[source]

Bases: NavienBaseModel

Base energy usage fields common to daily and total responses.

heat_element_time: int
heat_element_usage: int
heat_pump_time: int
heat_pump_usage: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property total_usage: int
class nwp500.models.energy.EnergyUsageDay(*, hpUsage: int = 0, heUsage: int = 0, hpTime: int = 0, heTime: int = 0)[source]

Bases: EnergyUsageBase

Daily energy usage data.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class nwp500.models.energy.EnergyUsageResponse(*, total: EnergyUsageTotal, usage: list[MonthlyEnergyData])[source]

Bases: NavienBaseModel

Response for energy usage query.

get_month_data(year: int, month: int) MonthlyEnergyData | None[source]

Get energy usage data for a specific month.

Parameters:
  • year – Year (e.g., 2025)

  • month – Month (1-12)

Returns:

MonthlyEnergyData for that month, or None if not found

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

total: EnergyUsageTotal
usage: list[MonthlyEnergyData]
class nwp500.models.energy.EnergyUsageTotal(*, hpUsage: int = 0, heUsage: int = 0, hpTime: int = 0, heTime: int = 0)[source]

Bases: EnergyUsageBase

Total energy usage data.

property heat_element_percentage: float
property heat_pump_percentage: float
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property total_time: int
class nwp500.models.energy.MonthlyEnergyData(*, year: int, month: int, data: list[EnergyUsageDay])[source]

Bases: NavienBaseModel

Monthly energy usage data grouping.

data: list[EnergyUsageDay]
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

month: int
year: int

nwp500.models.feature module

class nwp500.models.feature.DeviceFeature(*, temperatureType: ~nwp500.enums.TemperatureType = TemperatureType.FAHRENHEIT, macAddress: str | None = None, countryCode: int, modelTypeCode: ~nwp500.enums.UnitType | int, controlTypeCode: int, volumeCode: ~typing.Annotated[~nwp500.enums.VolumeCode, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.enum_validator.<locals>.validate, json_schema_input_type=PydanticUndefined)], controllerSwVersion: int, panelSwVersion: int, wifiSwVersion: int, controllerSwCode: int, panelSwCode: int, wifiSwCode: int, recircSwVersion: int, recircModelTypeCode: int, controllerSerialNumber: str, powerUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, holidayUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, programReservationUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwTemperatureSettingUse: ~nwp500.enums.DHWControlTypeFlag, smartDiagnosticUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, wifiRssiUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, tempFormulaType: ~nwp500.enums.TempFormulaType = TempFormulaType.ASYMMETRIC, energyUsageUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, freezeProtectionUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, mixingValveUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, drSettingUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, antiLegionellaSettingUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, hpwhUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwRefillUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, ecoUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, electricUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, heatpumpUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, energySaverUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, highDemandUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, recirculationUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, recircReservationUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, title24Use: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwTemperatureMin: int = None, dhwTemperatureMax: int = None, freezeProtectionTempMin: int = None, freezeProtectionTempMax: int = None, recircTemperatureMin: int = None, recircTemperatureMax: int = None)[source]

Bases: NavienBaseModel

Device capabilities, configuration, and firmware info.

Unit-aware note:

Temperature computed fields (e.g. dhw_temperature_min, dhw_temperature_max, recirc_temperature_min) read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

anti_legionella_setting_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
control_type_code: int
controller_serial_number: str
controller_sw_code: int
controller_sw_version: int
country_code: int
dhw_refill_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property dhw_temperature_max: float
dhw_temperature_max_raw: int
property dhw_temperature_min: float
dhw_temperature_min_raw: int
dhw_temperature_setting_use: DHWControlTypeFlag
dhw_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
dr_setting_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
eco_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
electric_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
energy_saver_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
energy_usage_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property freeze_protection_temp_max: float
freeze_protection_temp_max_raw: int
property freeze_protection_temp_min: float
freeze_protection_temp_min_raw: int
freeze_protection_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
get_field_unit(field_name: str) str[source]

Get the correct unit suffix based on temperature preference.

Resolves dynamic units for temperature, flow rate, and volume fields that change based on unit system context override or the device’s temperature_type setting (Celsius or Fahrenheit).

Parameters:

field_name – Name of the field to get the unit for

Returns:

Unit string (e.g., “ °C”, “ LPM”, “ L”) or empty if field not found

heatpump_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
high_demand_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
holiday_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
hpwh_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
mac_address: str | None
mixing_valve_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_type_code: UnitType | int
panel_sw_code: int
panel_sw_version: int
power_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
program_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
recirc_model_type_code: int
recirc_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
recirc_sw_version: int
property recirc_temperature_max: float
recirc_temperature_max_raw: int
property recirc_temperature_min: float
recirc_temperature_min_raw: int
recirculation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
smart_diagnostic_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
temp_formula_type: TempFormulaType
temperature_type: TemperatureType
title24_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
volume_code: validate, json_schema_input_type=PydanticUndefined)]
wifi_rssi_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
wifi_sw_code: int
wifi_sw_version: int

nwp500.models.mqtt_models module

class nwp500.models.mqtt_models.MqttCommand(*, clientID: str, sessionID: str, requestTopic: str, responseTopic: str, request: MqttRequest | dict[str, Any], protocolVersion: int = 2)[source]

Bases: NavienBaseModel

Represents an MQTT command message.

client_id: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

protocol_version: int
request: MqttRequest | dict[str, Any]
request_topic: str
response_topic: str
session_id: str
class nwp500.models.mqtt_models.MqttRequest(*, command: int, deviceType: DeviceType | int, macAddress: str, additionalValue: str = '...', mode: str | None = None, param: list[int | float] = <factory>, paramStr: str = '', month: list[int] | None = None, year: int | None = None)[source]

Bases: NavienBaseModel

MQTT command request payload.

additional_value: str
command: int
device_type: DeviceType | int
mac_address: str
mode: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

month: list[int] | None
param: list[int | float]
param_str: str
year: int | None

nwp500.models.schedule module

class nwp500.models.schedule.OtaCommitPayload(*, swCode: int, swVersion: int)[source]

Bases: NavienBaseModel

Payload for committing a firmware component update.

Used with the OTA_COMMIT command (33554442). This command uses a special commitOta structure instead of the standard mode/param format.

Parameters:
  • sw_code – Software component code identifying which firmware to commit. 1 = Controller, 2 = Panel, 4 = WiFi/communication module.

  • sw_version – Version number to commit (as reported by the OTA check).

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

sw_code: int
sw_version: int
class nwp500.models.schedule.RecirculationSchedule(*, schedule: list[RecirculationScheduleEntry] = <factory>)[source]

Bases: NavienBaseModel

Complete recirculation pump schedule (RECIR_RESERVATION command).

Used with command code 33554444 to configure timed recirculation pump operation windows.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

schedule: list[RecirculationScheduleEntry]
class nwp500.models.schedule.RecirculationScheduleEntry(*, enable: int = 2, week: int = 0, startHour: int = 0, startMin: int = 0, endHour: int = 0, endMin: int = 0, mode: int = 1)[source]

Bases: NavienBaseModel

A single entry in a recirculation pump schedule.

Used with the RECIR_RESERVATION command (33554444) to set timed recirculation cycles. Each entry defines a time window and pump mode.

Fields:
  • enable: 2=enabled, 1=disabled (device boolean)

  • week: bitfield of active days (Sun=bit7, Mon=bit6, …, Sat=bit1)

  • start_hour: 0-23

  • start_min: 0-59

  • end_hour: 0-23

  • end_min: 0-59

  • mode: recirculation mode (1=Constant, 2=Timer, 3=Temperature, 4=Sensor)

property days: list[str]

Weekday names for this entry.

enable: int
property enabled: bool

2=on, 1=off).

Type:

Whether this entry is active (device bool

end_hour: int
end_min: int
property end_time: str

MM).

Type:

Formatted end time string (HH

mode: int
property mode_name: str

Human-readable recirculation mode name.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start_hour: int
start_min: int
property start_time: str

MM).

Type:

Formatted start time string (HH

week: int
class nwp500.models.schedule.ReservationEntry(*, enable: int = 2, week: int = 0, hour: int = 0, min: int = 0, mode: int = 1, param: int = 0)[source]

Bases: NavienBaseModel

A single scheduled reservation entry.

Wraps the raw 6-byte protocol fields and provides computed properties for display-ready values including unit-aware temperature conversion.

The raw protocol fields are:
  • enable: 2=enabled, 1=disabled (device boolean)

  • week: bitfield of active days (Sun=bit7, Mon=bit6, …, Sat=bit1)

  • hour: 0-23

  • min: 0-59

  • mode: DHW operation mode ID (1-6)

  • param: temperature in half-degrees Celsius

Unit-aware note:

The temperature and unit computed fields read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

property days: list[str]

Weekday names for this reservation.

enable: int
property enabled: bool

2=on, 1=off).

Type:

Whether this reservation is active (device bool

hour: int
min: int
mode: int
property mode_name: str

Human-readable operation mode name.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

param: int
property temperature: float

Temperature in the user’s preferred unit.

property time: str

MM).

Type:

Formatted time string (HH

property unit: str

Temperature unit symbol.

week: int
class nwp500.models.schedule.ReservationSchedule(*, reservationUse: int = 0, reservation: list[ReservationEntry] = <factory>)[source]

Bases: NavienBaseModel

Complete reservation schedule from the device.

Can be constructed from raw MQTT response data. The reservation field accepts either a hex string (from GET responses) or a list of dicts/ReservationEntry objects.

property enabled: bool

Whether the reservation system is globally enabled.

Device bool convention: 2=on, 1=off.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

reservation: list[ReservationEntry]
reservation_use: int
class nwp500.models.schedule.WeeklyReservationEntry(*, enable: int = 2, week: int = 0, hour: int = 0, min: int = 0, mode: int = 1, param: int = 0)[source]

Bases: NavienBaseModel

A single entry in a weekly temperature reservation schedule.

Similar to ReservationEntry but used with the RESERVATION_WEEKLY command (33554438), which configures a separate weekly temperature schedule independent of the timed reservation system.

The raw protocol fields mirror the standard reservation format:
  • enable: 2=enabled, 1=disabled (device boolean)

  • week: bitfield of active days (Sun=bit7, Mon=bit6, …, Sat=bit1)

  • hour: 0-23

  • min: 0-59

  • mode: DHW operation mode ID (1-6)

  • param: temperature in half-degrees Celsius

Unit-aware note:

The temperature and unit computed fields read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

property days: list[str]

Weekday names for this entry.

enable: int
property enabled: bool

2=on, 1=off).

Type:

Whether this entry is active (device bool

hour: int
min: int
mode: int
property mode_name: str

Human-readable operation mode name.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

param: int
property temperature: float

Temperature in the user’s preferred unit.

property time: str

MM).

Type:

Formatted time string (HH

property unit: str

Temperature unit symbol.

week: int
class nwp500.models.schedule.WeeklyReservationSchedule(*, reservationUse: int = 0, reservation: list[WeeklyReservationEntry] = <factory>)[source]

Bases: NavienBaseModel

Complete weekly reservation schedule (RESERVATION_WEEKLY command).

Used with command code 33554438 to configure a temperature schedule that repeats weekly. Accepts the same hex-encoded format as the standard reservation schedule.

property enabled: bool

Whether the weekly reservation system is globally enabled.

Device bool convention: 2=on, 1=off.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

reservation: list[WeeklyReservationEntry]
reservation_use: int

nwp500.models.status module

class nwp500.models.status.DeviceStatus(*, temperatureType: TemperatureType = TemperatureType.FAHRENHEIT, macAddress: str | None = None, command: int, specialFunctionStatus: int, errorCode: ErrorCode = ErrorCode.NO_ERROR, subErrorCode: int, smartDiagnostic: int, faultStatus1: int, faultStatus2: int, wifiRssi: int = None, dhwChargePer: float, drEventStatus: DREvent = DREvent.UNKNOWN, vacationDaySetting: int, vacationDayElapsed: int, antiLegionellaPeriod: int, programReservationType: int, tempFormulaType: TempFormulaType, outsideTemperature: int = None, currentStatenum: int, targetFanRpm: int, currentFanRpm: int, fanPwm: int, mixingRate: float, eevStep: int, airFilterAlarmPeriod: int, airFilterAlarmElapsed: int, cumulatedOpTimeEvaFan: int, cumulatedDhwFlowRate: int, touStatus: Annotated[bool, BeforeValidator(func=bool, json_schema_input_type=PydanticUndefined)], drOverrideStatus: int, touOverrideStatus: Annotated[bool, BeforeValidator(func=tou_override_to_python, json_schema_input_type=PydanticUndefined)], totalEnergyCapacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)], availableEnergyCapacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)], recircOperationMode: RecirculationMode, recircPumpOperationStatus: int, recircHotBtnReady: int, recircOperationReason: int, recircErrorStatus: int, currentInstPower: float, didReload: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], operationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], freezeProtectionUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwUseSustained: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwOperationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, programReservationUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], ecoUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], compUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], eevUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], evaFanUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], shutOffValveUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], conOvrSensorUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], wtrOvrSensorUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], antiLegionellaUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], antiLegionellaOperationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], errorBuzzerUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], currentHeatUse: HeatSource, heatUpperUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], heatLowerUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], scaldUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], airFilterAlarmUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], recircOperationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], recircReservationUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwTemperature: int = None, dhwTemperatureSetting: int = None, dhwTargetTemperatureSetting: int = None, freezeProtectionTemperature: int = None, dhwTemperature2: int = None, hpUpperOnTempSetting: int = None, hpUpperOffTempSetting: int = None, hpLowerOnTempSetting: int = None, hpLowerOffTempSetting: int = None, heUpperOnTempSetting: int = None, heUpperOffTempSetting: int = None, heLowerOnTempSetting: int = None, heLowerOffTempSetting: int = None, heatMinOpTemperature: int = None, recircTempSetting: int = None, recircTemperature: int = None, recircFaucetTemperature: int = None, currentInletTemperature: int = None, currentDhwFlowRate: int, hpUpperOnDiffTempSetting: int, hpUpperOffDiffTempSetting: int, hpLowerOnDiffTempSetting: int, hpLowerOffDiffTempSetting: int, heUpperOnDiffTempSetting: int, heUpperOffDiffTempSetting: int, heLowerOnTDiffempSetting: int, heLowerOffDiffTempSetting: int, recircDhwFlowRate: int, tankUpperTemperature: int = None, tankLowerTemperature: int = None, dischargeTemperature: int = None, suctionTemperature: int = None, evaporatorTemperature: int = None, ambientTemperature: int = None, targetSuperHeat: int = None, currentSuperHeat: int = None, operationMode: CurrentOperationMode = CurrentOperationMode.STANDBY, dhwOperationSetting: DhwOperationSetting = DhwOperationSetting.ENERGY_SAVER, freezeProtectionTempMin: int = 12, freezeProtectionTempMax: int = 20)[source]

Bases: NavienBaseModel

Represents the status of the Navien water heater device.

Unit-aware note:

Temperature computed fields (e.g. dhw_temperature, outside_temperature, dhw_temperature_setting) read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

air_filter_alarm_elapsed: int
air_filter_alarm_period: int
air_filter_alarm_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property ambient_temperature: float
ambient_temperature_raw: int
anti_legionella_operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
anti_legionella_period: int
anti_legionella_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
available_energy_capacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)]
command: int
comp_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
con_ovr_sensor_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property cumulated_dhw_flow_rate: float
cumulated_dhw_flow_rate_raw: int
cumulated_op_time_eva_fan: int
property current_dhw_flow_rate: float
current_dhw_flow_rate_raw: int
current_fan_rpm: int
current_heat_use: HeatSource
property current_inlet_temperature: float
current_inlet_temperature_raw: int
current_inst_power: float
current_statenum: int
property current_super_heat: float
current_super_heat_raw: int
dhw_charge_per: float
dhw_operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
dhw_operation_setting: DhwOperationSetting
property dhw_target_temperature_setting: float
dhw_target_temperature_setting_raw: int
property dhw_temperature: float
property dhw_temperature2: float
dhw_temperature2_raw: int
dhw_temperature_raw: int
property dhw_temperature_setting: float
dhw_temperature_setting_raw: int
dhw_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
dhw_use_sustained: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
did_reload: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property discharge_temperature: float
discharge_temperature_raw: int
dr_event_status: DREvent
dr_override_status: int
eco_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
eev_step: int
eev_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
error_buzzer_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
error_code: ErrorCode
eva_fan_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property evaporator_temperature: float
evaporator_temperature_raw: int
fan_pwm: int
fault_status1: int
fault_status2: int
property freeze_protection_temp_max: float
freeze_protection_temp_max_raw: int
property freeze_protection_temp_min: float
freeze_protection_temp_min_raw: int
property freeze_protection_temperature: float
freeze_protection_temperature_raw: int
freeze_protection_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
get_field_unit(field_name: str) str[source]

Get the correct unit suffix based on temperature preference.

Resolves dynamic units for temperature, flow rate, and volume fields that change based on unit system context override or the device’s temperature_type setting (Celsius or Fahrenheit).

Parameters:

field_name – Name of the field to get the unit for

Returns:

Unit string (e.g., “ °C”, “ LPM”, “ L”) or empty if field not found

property he_lower_off_diff_temp_setting: float
he_lower_off_diff_temp_setting_raw: int
property he_lower_off_temp_setting: float
he_lower_off_temp_setting_raw: int
property he_lower_on_diff_temp_setting: float
he_lower_on_diff_temp_setting_raw: int
property he_lower_on_temp_setting: float
he_lower_on_temp_setting_raw: int
property he_upper_off_diff_temp_setting: float
he_upper_off_diff_temp_setting_raw: int
property he_upper_off_temp_setting: float
he_upper_off_temp_setting_raw: int
property he_upper_on_diff_temp_setting: float
he_upper_on_diff_temp_setting_raw: int
property he_upper_on_temp_setting: float
he_upper_on_temp_setting_raw: int
heat_lower_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property heat_min_op_temperature: float
heat_min_op_temperature_raw: int
heat_upper_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property hp_lower_off_diff_temp_setting: float
hp_lower_off_diff_temp_setting_raw: int
property hp_lower_off_temp_setting: float
hp_lower_off_temp_setting_raw: int
property hp_lower_on_diff_temp_setting: float
hp_lower_on_diff_temp_setting_raw: int
property hp_lower_on_temp_setting: float
hp_lower_on_temp_setting_raw: int
property hp_upper_off_diff_temp_setting: float
hp_upper_off_diff_temp_setting_raw: int
property hp_upper_off_temp_setting: float
hp_upper_off_temp_setting_raw: int
property hp_upper_on_diff_temp_setting: float
hp_upper_on_diff_temp_setting_raw: int
property hp_upper_on_temp_setting: float
hp_upper_on_temp_setting_raw: int
mac_address: str | None
mixing_rate: float
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
operation_mode: CurrentOperationMode
property outside_temperature: float
outside_temperature_raw: int
program_reservation_type: int
program_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property recirc_dhw_flow_rate: float
recirc_dhw_flow_rate_raw: int
recirc_error_status: int
property recirc_faucet_temperature: float
recirc_faucet_temperature_raw: int
recirc_hot_btn_ready: int
recirc_operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
recirc_operation_mode: RecirculationMode
recirc_operation_reason: int
recirc_pump_operation_status: int
recirc_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property recirc_temp_setting: float
recirc_temp_setting_raw: int
property recirc_temperature: float
recirc_temperature_raw: int
scald_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
shut_off_valve_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
smart_diagnostic: int
special_function_status: int
sub_error_code: int
property suction_temperature: float
suction_temperature_raw: int
property tank_lower_temperature: float
tank_lower_temperature_raw: int
property tank_upper_temperature: float
tank_upper_temperature_raw: int
target_fan_rpm: int
property target_super_heat: float
target_super_heat_raw: int
temp_formula_type: TempFormulaType
temperature_type: TemperatureType
total_energy_capacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)]
tou_override_status: Annotated[bool, BeforeValidator(func=tou_override_to_python, json_schema_input_type=PydanticUndefined)]
tou_status: Annotated[bool, BeforeValidator(func=bool, json_schema_input_type=PydanticUndefined)]
vacation_day_elapsed: int
vacation_day_setting: int
wifi_rssi: int
wtr_ovr_sensor_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]

nwp500.models.tou module

class nwp500.models.tou.ConvertedTOUPlan(*, utility: str = '', name: str = '', schedule: list[TOUSchedule] = <factory>)[source]

Bases: NavienBaseModel

A rate plan converted by the Navien backend from OpenEI format.

Returned by POST /device/tou/convert. Contains the utility name, plan name, and device-ready schedule with season/week bitfields and scaled pricing.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
schedule: list[TOUSchedule]
utility: str
class nwp500.models.tou.TOUInfo(*, registerPath: str = '', sourceType: str = '', controllerId: str = '', manufactureId: str = '', name: str = '', utility: str = '', zipCode: int = 0, schedule: list[TOUSchedule] = <factory>)[source]

Bases: NavienBaseModel

Time of Use information.

controller_id: str
manufacture_id: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
register_path: str
schedule: list[TOUSchedule]
source_type: str
utility: str
zip_code: int
class nwp500.models.tou.TOUPeriod(*, season: int = 0, week: int = 0, startHour: int = 0, startMinute: int = 0, endHour: int = 0, endMinute: int = 0, priceMin: int = 0, priceMax: int = 0, decimalPoint: int = 5)[source]

Bases: NavienBaseModel

A single TOU pricing period from an MQTT tou/rd response.

Each period defines a time window, active season/week bitfields, and the pricing range for that window.

Fields use camelCase aliases to match the raw MQTT payload:
  • season: bitfield of active months (bit N-1 set for month N)

  • week: bitfield of active weekdays (Sun=bit7, …, Sat=bit1)

  • startHour / startMinute: start of the time window (0-23 / 0-59)

  • endHour / endMinute: end of the time window (0-23 / 0-59)

  • priceMin / priceMax: encoded integer prices (divide by 10^decimalPoint)

  • decimalPoint: number of decimal places for price values

Unit-aware note:

Unlike temperature-bearing models such as DeviceStatus, the computed price and time fields here are independent of the process-wide unit-system preference (see nwp500.unit_system.get_unit_system() and issue #103); pricing is always decoded the same way regardless of the configured unit system.

decimal_point: int
property decoded_price_max: float

Maximum price decoded to a float (price_max / 10^decimal_point).

property decoded_price_min: float

Minimum price decoded to a float (price_min / 10^decimal_point).

end_hour: int
end_min: int
property end_time: str

MM).

Type:

Formatted end time (HH

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

price_max: int
price_min: int
season: int
start_hour: int
start_min: int
property start_time: str

MM).

Type:

Formatted start time (HH

week: int
class nwp500.models.tou.TOUReservationSchedule(*, reservationUse: int = 0, reservation: list[TOUPeriod] = <factory>)[source]

Bases: NavienBaseModel

TOU schedule as returned by the MQTT tou/rd response topic.

This model matches the raw MQTT payload for both request_tou_settings() read responses and configure_tou_schedule() write confirmations — both use CommandCode.TOU_RESERVATION and the tou/rd response topic.

The payload structure is:

{
    "reservationUse": 2,          # 0=disabled, 2=enabled
    "reservation": [              # list of TOU period dicts
        {
            "season": 4095, "week": 254,
            "startHour": 0, "startMinute": 0,
            "endHour": 23, "endMinute": 59,
            "priceMin": 10, "priceMax": 25,
            "decimalPoint": 2
        },
        ...
    ]
}
property enabled: bool

Whether TOU scheduling is globally enabled.

Protocol convention: 0=disabled, 2=enabled.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

reservation: list[TOUPeriod]
reservation_use: int
class nwp500.models.tou.TOUSchedule(*, season: int = 0, interval: list[dict[str, ~typing.Any]]=<factory>)[source]

Bases: NavienBaseModel

Time of Use schedule information.

intervals: list[dict[str, Any]]
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

season: int

Module contents

Data models for Navien NWP500 water heater communication.

This module defines data classes for representing data structures used in the Navien NWP500 water heater communication protocol.

These models are based on the MQTT message formats and API responses.

class nwp500.models.ConvertedTOUPlan(*, utility: str = '', name: str = '', schedule: list[TOUSchedule] = <factory>)[source]

Bases: NavienBaseModel

A rate plan converted by the Navien backend from OpenEI format.

Returned by POST /device/tou/convert. Contains the utility name, plan name, and device-ready schedule with season/week bitfields and scaled pricing.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
schedule: list[TOUSchedule]
utility: str
class nwp500.models.Device(*, deviceInfo: DeviceInfo, location: Location)[source]

Bases: NavienBaseModel

Complete device information including location.

device_info: DeviceInfo
location: Location
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

with_info(info: DeviceInfo) Self[source]

Return a new Device instance with updated DeviceInfo.

class nwp500.models.DeviceFeature(*, temperatureType: ~nwp500.enums.TemperatureType = TemperatureType.FAHRENHEIT, macAddress: str | None = None, countryCode: int, modelTypeCode: ~nwp500.enums.UnitType | int, controlTypeCode: int, volumeCode: ~typing.Annotated[~nwp500.enums.VolumeCode, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.enum_validator.<locals>.validate, json_schema_input_type=PydanticUndefined)], controllerSwVersion: int, panelSwVersion: int, wifiSwVersion: int, controllerSwCode: int, panelSwCode: int, wifiSwCode: int, recircSwVersion: int, recircModelTypeCode: int, controllerSerialNumber: str, powerUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, holidayUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, programReservationUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwTemperatureSettingUse: ~nwp500.enums.DHWControlTypeFlag, smartDiagnosticUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, wifiRssiUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, tempFormulaType: ~nwp500.enums.TempFormulaType = TempFormulaType.ASYMMETRIC, energyUsageUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, freezeProtectionUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, mixingValveUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, drSettingUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, antiLegionellaSettingUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, hpwhUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwRefillUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, ecoUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, electricUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, heatpumpUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, energySaverUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, highDemandUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, recirculationUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, recircReservationUse: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, title24Use: ~typing.Annotated[bool, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, dhwTemperatureMin: int = None, dhwTemperatureMax: int = None, freezeProtectionTempMin: int = None, freezeProtectionTempMax: int = None, recircTemperatureMin: int = None, recircTemperatureMax: int = None)[source]

Bases: NavienBaseModel

Device capabilities, configuration, and firmware info.

Unit-aware note:

Temperature computed fields (e.g. dhw_temperature_min, dhw_temperature_max, recirc_temperature_min) read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

anti_legionella_setting_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
control_type_code: int
controller_serial_number: str
controller_sw_code: int
controller_sw_version: int
country_code: int
dhw_refill_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property dhw_temperature_max: float
dhw_temperature_max_raw: int
property dhw_temperature_min: float
dhw_temperature_min_raw: int
dhw_temperature_setting_use: DHWControlTypeFlag
dhw_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
dr_setting_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
eco_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
electric_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
energy_saver_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
energy_usage_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property freeze_protection_temp_max: float
freeze_protection_temp_max_raw: int
property freeze_protection_temp_min: float
freeze_protection_temp_min_raw: int
freeze_protection_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
get_field_unit(field_name: str) str[source]

Get the correct unit suffix based on temperature preference.

Resolves dynamic units for temperature, flow rate, and volume fields that change based on unit system context override or the device’s temperature_type setting (Celsius or Fahrenheit).

Parameters:

field_name – Name of the field to get the unit for

Returns:

Unit string (e.g., “ °C”, “ LPM”, “ L”) or empty if field not found

heatpump_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
high_demand_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
holiday_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
hpwh_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
mac_address: str | None
mixing_valve_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_type_code: UnitType | int
panel_sw_code: int
panel_sw_version: int
power_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
program_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
recirc_model_type_code: int
recirc_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
recirc_sw_version: int
property recirc_temperature_max: float
recirc_temperature_max_raw: int
property recirc_temperature_min: float
recirc_temperature_min_raw: int
recirculation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
smart_diagnostic_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
temp_formula_type: TempFormulaType
temperature_type: TemperatureType
title24_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
volume_code: validate, json_schema_input_type=PydanticUndefined)]
wifi_rssi_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
wifi_sw_code: int
wifi_sw_version: int
class nwp500.models.DeviceInfo(*, homeSeq: int = 0, macAddress: str = '', additionalValue: str = '', deviceType: DeviceType | int = DeviceType.NPF700_WIFI, deviceName: str = 'Unknown', connected: ConnectionStatus, ~pydantic.functional_validators.BeforeValidator(func=~nwp500.converters.enum_validator.<locals>.validate, json_schema_input_type=PydanticUndefined)] = ConnectionStatus.DISCONNECTED, installType: str | None = None)[source]

Bases: NavienBaseModel

Device information from API.

additional_value: str
connected: validate, json_schema_input_type=PydanticUndefined)]
device_name: str
device_type: DeviceType | int
home_seq: int
install_type: str | None
mac_address: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class nwp500.models.DeviceStatus(*, temperatureType: TemperatureType = TemperatureType.FAHRENHEIT, macAddress: str | None = None, command: int, specialFunctionStatus: int, errorCode: ErrorCode = ErrorCode.NO_ERROR, subErrorCode: int, smartDiagnostic: int, faultStatus1: int, faultStatus2: int, wifiRssi: int = None, dhwChargePer: float, drEventStatus: DREvent = DREvent.UNKNOWN, vacationDaySetting: int, vacationDayElapsed: int, antiLegionellaPeriod: int, programReservationType: int, tempFormulaType: TempFormulaType, outsideTemperature: int = None, currentStatenum: int, targetFanRpm: int, currentFanRpm: int, fanPwm: int, mixingRate: float, eevStep: int, airFilterAlarmPeriod: int, airFilterAlarmElapsed: int, cumulatedOpTimeEvaFan: int, cumulatedDhwFlowRate: int, touStatus: Annotated[bool, BeforeValidator(func=bool, json_schema_input_type=PydanticUndefined)], drOverrideStatus: int, touOverrideStatus: Annotated[bool, BeforeValidator(func=tou_override_to_python, json_schema_input_type=PydanticUndefined)], totalEnergyCapacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)], availableEnergyCapacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)], recircOperationMode: RecirculationMode, recircPumpOperationStatus: int, recircHotBtnReady: int, recircOperationReason: int, recircErrorStatus: int, currentInstPower: float, didReload: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], operationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], freezeProtectionUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwUseSustained: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwOperationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)] = False, programReservationUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], ecoUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], compUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], eevUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], evaFanUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], shutOffValveUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], conOvrSensorUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], wtrOvrSensorUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], antiLegionellaUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], antiLegionellaOperationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], errorBuzzerUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], currentHeatUse: HeatSource, heatUpperUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], heatLowerUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], scaldUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], airFilterAlarmUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], recircOperationBusy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], recircReservationUse: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)], dhwTemperature: int = None, dhwTemperatureSetting: int = None, dhwTargetTemperatureSetting: int = None, freezeProtectionTemperature: int = None, dhwTemperature2: int = None, hpUpperOnTempSetting: int = None, hpUpperOffTempSetting: int = None, hpLowerOnTempSetting: int = None, hpLowerOffTempSetting: int = None, heUpperOnTempSetting: int = None, heUpperOffTempSetting: int = None, heLowerOnTempSetting: int = None, heLowerOffTempSetting: int = None, heatMinOpTemperature: int = None, recircTempSetting: int = None, recircTemperature: int = None, recircFaucetTemperature: int = None, currentInletTemperature: int = None, currentDhwFlowRate: int, hpUpperOnDiffTempSetting: int, hpUpperOffDiffTempSetting: int, hpLowerOnDiffTempSetting: int, hpLowerOffDiffTempSetting: int, heUpperOnDiffTempSetting: int, heUpperOffDiffTempSetting: int, heLowerOnTDiffempSetting: int, heLowerOffDiffTempSetting: int, recircDhwFlowRate: int, tankUpperTemperature: int = None, tankLowerTemperature: int = None, dischargeTemperature: int = None, suctionTemperature: int = None, evaporatorTemperature: int = None, ambientTemperature: int = None, targetSuperHeat: int = None, currentSuperHeat: int = None, operationMode: CurrentOperationMode = CurrentOperationMode.STANDBY, dhwOperationSetting: DhwOperationSetting = DhwOperationSetting.ENERGY_SAVER, freezeProtectionTempMin: int = 12, freezeProtectionTempMax: int = 20)[source]

Bases: NavienBaseModel

Represents the status of the Navien water heater device.

Unit-aware note:

Temperature computed fields (e.g. dhw_temperature, outside_temperature, dhw_temperature_setting) read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

air_filter_alarm_elapsed: int
air_filter_alarm_period: int
air_filter_alarm_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property ambient_temperature: float
ambient_temperature_raw: int
anti_legionella_operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
anti_legionella_period: int
anti_legionella_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
available_energy_capacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)]
command: int
comp_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
con_ovr_sensor_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property cumulated_dhw_flow_rate: float
cumulated_dhw_flow_rate_raw: int
cumulated_op_time_eva_fan: int
property current_dhw_flow_rate: float
current_dhw_flow_rate_raw: int
current_fan_rpm: int
current_heat_use: HeatSource
property current_inlet_temperature: float
current_inlet_temperature_raw: int
current_inst_power: float
current_statenum: int
property current_super_heat: float
current_super_heat_raw: int
dhw_charge_per: float
dhw_operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
dhw_operation_setting: DhwOperationSetting
property dhw_target_temperature_setting: float
dhw_target_temperature_setting_raw: int
property dhw_temperature: float
property dhw_temperature2: float
dhw_temperature2_raw: int
dhw_temperature_raw: int
property dhw_temperature_setting: float
dhw_temperature_setting_raw: int
dhw_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
dhw_use_sustained: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
did_reload: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property discharge_temperature: float
discharge_temperature_raw: int
dr_event_status: DREvent
dr_override_status: int
eco_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
eev_step: int
eev_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
error_buzzer_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
error_code: ErrorCode
eva_fan_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property evaporator_temperature: float
evaporator_temperature_raw: int
fan_pwm: int
fault_status1: int
fault_status2: int
property freeze_protection_temp_max: float
freeze_protection_temp_max_raw: int
property freeze_protection_temp_min: float
freeze_protection_temp_min_raw: int
property freeze_protection_temperature: float
freeze_protection_temperature_raw: int
freeze_protection_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
get_field_unit(field_name: str) str[source]

Get the correct unit suffix based on temperature preference.

Resolves dynamic units for temperature, flow rate, and volume fields that change based on unit system context override or the device’s temperature_type setting (Celsius or Fahrenheit).

Parameters:

field_name – Name of the field to get the unit for

Returns:

Unit string (e.g., “ °C”, “ LPM”, “ L”) or empty if field not found

property he_lower_off_diff_temp_setting: float
he_lower_off_diff_temp_setting_raw: int
property he_lower_off_temp_setting: float
he_lower_off_temp_setting_raw: int
property he_lower_on_diff_temp_setting: float
he_lower_on_diff_temp_setting_raw: int
property he_lower_on_temp_setting: float
he_lower_on_temp_setting_raw: int
property he_upper_off_diff_temp_setting: float
he_upper_off_diff_temp_setting_raw: int
property he_upper_off_temp_setting: float
he_upper_off_temp_setting_raw: int
property he_upper_on_diff_temp_setting: float
he_upper_on_diff_temp_setting_raw: int
property he_upper_on_temp_setting: float
he_upper_on_temp_setting_raw: int
heat_lower_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property heat_min_op_temperature: float
heat_min_op_temperature_raw: int
heat_upper_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property hp_lower_off_diff_temp_setting: float
hp_lower_off_diff_temp_setting_raw: int
property hp_lower_off_temp_setting: float
hp_lower_off_temp_setting_raw: int
property hp_lower_on_diff_temp_setting: float
hp_lower_on_diff_temp_setting_raw: int
property hp_lower_on_temp_setting: float
hp_lower_on_temp_setting_raw: int
property hp_upper_off_diff_temp_setting: float
hp_upper_off_diff_temp_setting_raw: int
property hp_upper_off_temp_setting: float
hp_upper_off_temp_setting_raw: int
property hp_upper_on_diff_temp_setting: float
hp_upper_on_diff_temp_setting_raw: int
property hp_upper_on_temp_setting: float
hp_upper_on_temp_setting_raw: int
mac_address: str | None
mixing_rate: float
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
operation_mode: CurrentOperationMode
property outside_temperature: float
outside_temperature_raw: int
program_reservation_type: int
program_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property recirc_dhw_flow_rate: float
recirc_dhw_flow_rate_raw: int
recirc_error_status: int
property recirc_faucet_temperature: float
recirc_faucet_temperature_raw: int
recirc_hot_btn_ready: int
recirc_operation_busy: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
recirc_operation_mode: RecirculationMode
recirc_operation_reason: int
recirc_pump_operation_status: int
recirc_reservation_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
property recirc_temp_setting: float
recirc_temp_setting_raw: int
property recirc_temperature: float
recirc_temperature_raw: int
scald_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
shut_off_valve_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
smart_diagnostic: int
special_function_status: int
sub_error_code: int
property suction_temperature: float
suction_temperature_raw: int
property tank_lower_temperature: float
tank_lower_temperature_raw: int
property tank_upper_temperature: float
tank_upper_temperature_raw: int
target_fan_rpm: int
property target_super_heat: float
target_super_heat_raw: int
temp_formula_type: TempFormulaType
temperature_type: TemperatureType
total_energy_capacity: Annotated[float, BeforeValidator(func=mul_10, json_schema_input_type=PydanticUndefined)]
tou_override_status: Annotated[bool, BeforeValidator(func=tou_override_to_python, json_schema_input_type=PydanticUndefined)]
tou_status: Annotated[bool, BeforeValidator(func=bool, json_schema_input_type=PydanticUndefined)]
vacation_day_elapsed: int
vacation_day_setting: int
wifi_rssi: int
wtr_ovr_sensor_use: Annotated[bool, BeforeValidator(func=device_bool_to_python, json_schema_input_type=PydanticUndefined)]
class nwp500.models.EnergyUsageBase(*, hpUsage: int = 0, heUsage: int = 0, hpTime: int = 0, heTime: int = 0)[source]

Bases: NavienBaseModel

Base energy usage fields common to daily and total responses.

heat_element_time: int
heat_element_usage: int
heat_pump_time: int
heat_pump_usage: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property total_usage: int
class nwp500.models.EnergyUsageDay(*, hpUsage: int = 0, heUsage: int = 0, hpTime: int = 0, heTime: int = 0)[source]

Bases: EnergyUsageBase

Daily energy usage data.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class nwp500.models.EnergyUsageResponse(*, total: EnergyUsageTotal, usage: list[MonthlyEnergyData])[source]

Bases: NavienBaseModel

Response for energy usage query.

get_month_data(year: int, month: int) MonthlyEnergyData | None[source]

Get energy usage data for a specific month.

Parameters:
  • year – Year (e.g., 2025)

  • month – Month (1-12)

Returns:

MonthlyEnergyData for that month, or None if not found

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

total: EnergyUsageTotal
usage: list[MonthlyEnergyData]
class nwp500.models.EnergyUsageTotal(*, hpUsage: int = 0, heUsage: int = 0, hpTime: int = 0, heTime: int = 0)[source]

Bases: EnergyUsageBase

Total energy usage data.

property heat_element_percentage: float
property heat_pump_percentage: float
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property total_time: int
class nwp500.models.FirmwareInfo(*, macAddress: str = '', additionalValue: str = '', deviceType: DeviceType | int = DeviceType.NPF700_WIFI, curSwCode: int = 0, curVersion: int = 0, downloadedVersion: int | None = None, deviceGroup: str | None = None)[source]

Bases: NavienBaseModel

Firmware information for a device.

additional_value: str
cur_sw_code: int
cur_version: int
device_group: str | None
device_type: DeviceType | int
downloaded_version: int | None
mac_address: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class nwp500.models.Location(*, state: str | None = None, city: str | None = None, address: str | None = None, latitude: float | None = None, longitude: float | None = None, altitude: float | None = None)[source]

Bases: NavienBaseModel

Location information for a device.

address: str | None
altitude: float | None
city: str | None
latitude: float | None
longitude: float | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

state: str | None
class nwp500.models.MonthlyEnergyData(*, year: int, month: int, data: list[EnergyUsageDay])[source]

Bases: NavienBaseModel

Monthly energy usage data grouping.

data: list[EnergyUsageDay]
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

month: int
year: int
class nwp500.models.MqttCommand(*, clientID: str, sessionID: str, requestTopic: str, responseTopic: str, request: MqttRequest | dict[str, Any], protocolVersion: int = 2)[source]

Bases: NavienBaseModel

Represents an MQTT command message.

client_id: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

protocol_version: int
request: MqttRequest | dict[str, Any]
request_topic: str
response_topic: str
session_id: str
class nwp500.models.MqttRequest(*, command: int, deviceType: DeviceType | int, macAddress: str, additionalValue: str = '...', mode: str | None = None, param: list[int | float] = <factory>, paramStr: str = '', month: list[int] | None = None, year: int | None = None)[source]

Bases: NavienBaseModel

MQTT command request payload.

additional_value: str
command: int
device_type: DeviceType | int
mac_address: str
mode: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

month: list[int] | None
param: list[int | float]
param_str: str
year: int | None
class nwp500.models.NavienBaseModel[source]

Bases: BaseModel

Base model for all Navien models.

Provides: - camelCase alias generation (to_camel) for JSON compatibility - populate_by_name=True so Python snake_case names work too - extra="ignore" to tolerate unknown protocol fields - use_enum_values=False to keep enum objects during validation - Custom model_dump that converts enums to their .name string

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_dump(**kwargs: Any) dict[str, Any][source]

Dump model to dict with enums serialised as their name strings.

to_protocol_dict() dict[str, Any][source]

Dump only the declared protocol fields, by alias.

Excludes pydantic computed_field properties, which are display-oriented (formatted times, weekday names, unit-converted temperatures) and must never be sent to the device.

class nwp500.models.OtaCommitPayload(*, swCode: int, swVersion: int)[source]

Bases: NavienBaseModel

Payload for committing a firmware component update.

Used with the OTA_COMMIT command (33554442). This command uses a special commitOta structure instead of the standard mode/param format.

Parameters:
  • sw_code – Software component code identifying which firmware to commit. 1 = Controller, 2 = Panel, 4 = WiFi/communication module.

  • sw_version – Version number to commit (as reported by the OTA check).

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

sw_code: int
sw_version: int
class nwp500.models.RecirculationSchedule(*, schedule: list[RecirculationScheduleEntry] = <factory>)[source]

Bases: NavienBaseModel

Complete recirculation pump schedule (RECIR_RESERVATION command).

Used with command code 33554444 to configure timed recirculation pump operation windows.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

schedule: list[RecirculationScheduleEntry]
class nwp500.models.RecirculationScheduleEntry(*, enable: int = 2, week: int = 0, startHour: int = 0, startMin: int = 0, endHour: int = 0, endMin: int = 0, mode: int = 1)[source]

Bases: NavienBaseModel

A single entry in a recirculation pump schedule.

Used with the RECIR_RESERVATION command (33554444) to set timed recirculation cycles. Each entry defines a time window and pump mode.

Fields:
  • enable: 2=enabled, 1=disabled (device boolean)

  • week: bitfield of active days (Sun=bit7, Mon=bit6, …, Sat=bit1)

  • start_hour: 0-23

  • start_min: 0-59

  • end_hour: 0-23

  • end_min: 0-59

  • mode: recirculation mode (1=Constant, 2=Timer, 3=Temperature, 4=Sensor)

property days: list[str]

Weekday names for this entry.

enable: int
property enabled: bool

2=on, 1=off).

Type:

Whether this entry is active (device bool

end_hour: int
end_min: int
property end_time: str

MM).

Type:

Formatted end time string (HH

mode: int
property mode_name: str

Human-readable recirculation mode name.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start_hour: int
start_min: int
property start_time: str

MM).

Type:

Formatted start time string (HH

week: int
class nwp500.models.ReservationEntry(*, enable: int = 2, week: int = 0, hour: int = 0, min: int = 0, mode: int = 1, param: int = 0)[source]

Bases: NavienBaseModel

A single scheduled reservation entry.

Wraps the raw 6-byte protocol fields and provides computed properties for display-ready values including unit-aware temperature conversion.

The raw protocol fields are:
  • enable: 2=enabled, 1=disabled (device boolean)

  • week: bitfield of active days (Sun=bit7, Mon=bit6, …, Sat=bit1)

  • hour: 0-23

  • min: 0-59

  • mode: DHW operation mode ID (1-6)

  • param: temperature in half-degrees Celsius

Unit-aware note:

The temperature and unit computed fields read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

property days: list[str]

Weekday names for this reservation.

enable: int
property enabled: bool

2=on, 1=off).

Type:

Whether this reservation is active (device bool

hour: int
min: int
mode: int
property mode_name: str

Human-readable operation mode name.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

param: int
property temperature: float

Temperature in the user’s preferred unit.

property time: str

MM).

Type:

Formatted time string (HH

property unit: str

Temperature unit symbol.

week: int
class nwp500.models.ReservationSchedule(*, reservationUse: int = 0, reservation: list[ReservationEntry] = <factory>)[source]

Bases: NavienBaseModel

Complete reservation schedule from the device.

Can be constructed from raw MQTT response data. The reservation field accepts either a hex string (from GET responses) or a list of dicts/ReservationEntry objects.

property enabled: bool

Whether the reservation system is globally enabled.

Device bool convention: 2=on, 1=off.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

reservation: list[ReservationEntry]
reservation_use: int
class nwp500.models.TOUInfo(*, registerPath: str = '', sourceType: str = '', controllerId: str = '', manufactureId: str = '', name: str = '', utility: str = '', zipCode: int = 0, schedule: list[TOUSchedule] = <factory>)[source]

Bases: NavienBaseModel

Time of Use information.

controller_id: str
manufacture_id: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
register_path: str
schedule: list[TOUSchedule]
source_type: str
utility: str
zip_code: int
class nwp500.models.TOUPeriod(*, season: int = 0, week: int = 0, startHour: int = 0, startMinute: int = 0, endHour: int = 0, endMinute: int = 0, priceMin: int = 0, priceMax: int = 0, decimalPoint: int = 5)[source]

Bases: NavienBaseModel

A single TOU pricing period from an MQTT tou/rd response.

Each period defines a time window, active season/week bitfields, and the pricing range for that window.

Fields use camelCase aliases to match the raw MQTT payload:
  • season: bitfield of active months (bit N-1 set for month N)

  • week: bitfield of active weekdays (Sun=bit7, …, Sat=bit1)

  • startHour / startMinute: start of the time window (0-23 / 0-59)

  • endHour / endMinute: end of the time window (0-23 / 0-59)

  • priceMin / priceMax: encoded integer prices (divide by 10^decimalPoint)

  • decimalPoint: number of decimal places for price values

Unit-aware note:

Unlike temperature-bearing models such as DeviceStatus, the computed price and time fields here are independent of the process-wide unit-system preference (see nwp500.unit_system.get_unit_system() and issue #103); pricing is always decoded the same way regardless of the configured unit system.

decimal_point: int
property decoded_price_max: float

Maximum price decoded to a float (price_max / 10^decimal_point).

property decoded_price_min: float

Minimum price decoded to a float (price_min / 10^decimal_point).

end_hour: int
end_min: int
property end_time: str

MM).

Type:

Formatted end time (HH

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

price_max: int
price_min: int
season: int
start_hour: int
start_min: int
property start_time: str

MM).

Type:

Formatted start time (HH

week: int
class nwp500.models.TOUReservationSchedule(*, reservationUse: int = 0, reservation: list[TOUPeriod] = <factory>)[source]

Bases: NavienBaseModel

TOU schedule as returned by the MQTT tou/rd response topic.

This model matches the raw MQTT payload for both request_tou_settings() read responses and configure_tou_schedule() write confirmations — both use CommandCode.TOU_RESERVATION and the tou/rd response topic.

The payload structure is:

{
    "reservationUse": 2,          # 0=disabled, 2=enabled
    "reservation": [              # list of TOU period dicts
        {
            "season": 4095, "week": 254,
            "startHour": 0, "startMinute": 0,
            "endHour": 23, "endMinute": 59,
            "priceMin": 10, "priceMax": 25,
            "decimalPoint": 2
        },
        ...
    ]
}
property enabled: bool

Whether TOU scheduling is globally enabled.

Protocol convention: 0=disabled, 2=enabled.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

reservation: list[TOUPeriod]
reservation_use: int
class nwp500.models.TOUSchedule(*, season: int = 0, interval: list[dict[str, ~typing.Any]]=<factory>)[source]

Bases: NavienBaseModel

Time of Use schedule information.

intervals: list[dict[str, Any]]
model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

season: int
class nwp500.models.WeeklyReservationEntry(*, enable: int = 2, week: int = 0, hour: int = 0, min: int = 0, mode: int = 1, param: int = 0)[source]

Bases: NavienBaseModel

A single entry in a weekly temperature reservation schedule.

Similar to ReservationEntry but used with the RESERVATION_WEEKLY command (33554438), which configures a separate weekly temperature schedule independent of the timed reservation system.

The raw protocol fields mirror the standard reservation format:
  • enable: 2=enabled, 1=disabled (device boolean)

  • week: bitfield of active days (Sun=bit7, Mon=bit6, …, Sat=bit1)

  • hour: 0-23

  • min: 0-59

  • mode: DHW operation mode ID (1-6)

  • param: temperature in half-degrees Celsius

Unit-aware note:

The temperature and unit computed fields read the process-wide unit-system preference via nwp500.unit_system.get_unit_system() at access time, not at construction time. Changing the preference with nwp500.unit_system.set_unit_system() therefore affects values read from already-constructed instances, and the preference is shared across every async task and thread rather than being context-local (see issue #103).

property days: list[str]

Weekday names for this entry.

enable: int
property enabled: bool

2=on, 1=off).

Type:

Whether this entry is active (device bool

hour: int
min: int
mode: int
property mode_name: str

Human-readable operation mode name.

model_config = {'alias_generator': <function to_camel>, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

param: int
property temperature: float

Temperature in the user’s preferred unit.

property time: str

MM).

Type:

Formatted time string (HH

property unit: str

Temperature unit symbol.

week: int
class nwp500.models.WeeklyReservationSchedule(*, reservationUse: int = 0, reservation: list[WeeklyReservationEntry] = <factory>)[source]

Bases: NavienBaseModel

Complete weekly reservation schedule (RESERVATION_WEEKLY command).

Used with command code 33554438 to configure a temperature schedule that repeats weekly. Accepts the same hex-encoded format as the standard reservation schedule.

property enabled: bool

Whether the weekly reservation system is globally enabled.

Device bool convention: 2=on, 1=off.

model_config = {'alias_generator': None, 'extra': 'ignore', 'populate_by_name': True, 'use_enum_values': False, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

reservation: list[WeeklyReservationEntry]
reservation_use: int
nwp500.models.fahrenheit_to_half_celsius(fahrenheit: float) int[source]

Convert Fahrenheit to half-degrees Celsius (for device commands).

Parameters:

fahrenheit – Temperature in Fahrenheit.

Returns:

Raw device value in half-Celsius format.

Example

>>> fahrenheit_to_half_celsius(140.0)
120
nwp500.models.preferred_to_half_celsius(temperature: float) int[source]

Convert temperature from preferred unit to half-degrees Celsius.

Converts temperature from the user’s preferred unit (Celsius or Fahrenheit, based on global unit system context) to the half-Celsius format used by the device for commands and reservations.

Parameters:

temperature – Temperature in user’s preferred unit (Celsius or Fahrenheit).

Returns:

Raw device value in half-Celsius format.

Example

>>> # With us_customary unit system
>>> preferred_to_half_celsius(140.0)  # 140°F
120
>>> # With metric unit system
>>> preferred_to_half_celsius(60.0)  # 60°C
120
nwp500.models.reservation_param_to_preferred(param: int) float[source]

Convert reservation param to user’s preferred temperature unit.

Device returns reservation temperatures as half-degrees Celsius (param). This converts them to the user’s preferred unit (Celsius or Fahrenheit) based on the global unit system context.

Parameters:

param – Raw device value in half-Celsius format.

Returns:

Temperature in user’s preferred unit (Celsius or Fahrenheit).

Example

>>> # With metric (Celsius) unit system
>>> reservation_param_to_preferred(120)
60.0
>>> # With us_customary (Fahrenheit) unit system
>>> reservation_param_to_preferred(120)
140.0